#ifndef _WIFI_HPP
#define _WIFI_HPP

/* 
wifi连接类型
0	在NVS中读取信息连接
1	配网连接
 */
static int wifiConType;

// wifi
static wifi_config_t wifiConfig;

void wifiInit();
static void wifiCheckWifiCon();
static void wifiEvent(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
static void wifiSmartconfig(void *arg);


void wifiInit() {
	wifiConType = 0;
	pageInfoAdd("Init WIFI...");
	ESP_ERROR_CHECK(esp_netif_init());
	ESP_ERROR_CHECK(esp_event_loop_create_default());

	esp_netif_t *staNetif = esp_netif_create_default_wifi_sta();
	assert(staNetif);

	// 初始化WIFI
	wifi_init_config_t initConfig = WIFI_INIT_CONFIG_DEFAULT();
	ESP_ERROR_CHECK(esp_wifi_init(&initConfig));

	// 检查WIFI连接方式，如果NVS中存有WIFI配置信息，则使用，否则进行配网。
	wifiCheckWifiCon();

	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifiEvent, NULL));
	ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifiEvent, NULL));
	ESP_ERROR_CHECK(esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &wifiEvent, NULL));

	ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
	ESP_ERROR_CHECK(esp_wifi_start());
	
	vTaskDelete(NULL);
}

static void wifiEvent(void *arg, esp_event_base_t base, int32_t id, void *data) {
	// wifi事件
	if(base == WIFI_EVENT) {
		if(id == WIFI_EVENT_STA_START) {
			pageInfoAdd("WIFI start.");
			if(wifiConType == 0) {
				ESP_ERROR_CHECK(esp_wifi_connect());
			}
			else if(wifiConType == 1) {
				xTaskCreate(wifiSmartconfig, "wifiSmartconfig", 4096, NULL, 0, NULL);
			}
		}
		else if(id == WIFI_EVENT_SCAN_DONE) {
			pageInfoAdd("WIFI scan done.");
		}
		else if(id == WIFI_EVENT_STA_DISCONNECTED) {
			xEventGroupClearBits(eventGroup, EVENT_WIFI_CONNECTED);
			xEventGroupSetBits(eventGroup, EVENT_WIFI_DISCONNECTED);
			esp_wifi_connect();
		}
	}
	else if(base == IP_EVENT) {
		if(id == IP_EVENT_STA_GOT_IP) {
			pageInfoAdd("WIFI init done.");
			ip_event_got_ip_t* event = (ip_event_got_ip_t*) data;
			sprintf(localIP, IPSTR, IP2STR(&event->ip_info.ip));
			pageInfoAdd("Local IP: ");
			pageInfoAdd(localIP);
			xEventGroupClearBits(eventGroup, EVENT_WIFI_DISCONNECTED);
			xEventGroupSetBits(eventGroup, EVENT_WIFI_CONNECTED);
		}
	}
	else if(base == SC_EVENT) {
		if(id == SC_EVENT_SCAN_DONE) {
			pageInfoAdd("WIFI scan done.");
		}
		else if(id == SC_EVENT_FOUND_CHANNEL) {
			pageInfoAdd("WIFI found channel.");
		}
		else if(id == SC_EVENT_GOT_SSID_PSWD) {
			pageInfoAdd("WIFI got SSID and PASSWORD from smartconfig.");
			smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)data;
			uint8_t ssid[33] = { 0 };
			uint8_t password[65] = { 0 };
			uint8_t rvd_data[33] = { 0 };

			bzero(&wifiConfig, sizeof(wifi_config_t));
			memcpy(wifiConfig.sta.ssid, evt->ssid, sizeof(wifiConfig.sta.ssid));
			memcpy(wifiConfig.sta.password, evt->password, sizeof(wifiConfig.sta.password));
			wifiConfig.sta.bssid_set = evt->bssid_set;
			if (wifiConfig.sta.bssid_set == true) {
				memcpy(wifiConfig.sta.bssid, evt->bssid, sizeof(wifiConfig.sta.bssid));
			}

			memcpy(ssid, evt->ssid, sizeof(evt->ssid));
			memcpy(password, evt->password, sizeof(evt->password));
			// ESP_LOGI(TAG, "SSID:%s", ssid);
			// ESP_LOGI(TAG, "PASSWORD:%s", password);

			// 写入NVS
			ESP_ERROR_CHECK(nvs_open("wifiConfig", NVS_READWRITE, &nvsHandle));
			ESP_ERROR_CHECK(nvs_set_u8(nvsHandle, "wifiConfigFlag", 1));
			ESP_ERROR_CHECK(nvs_set_str(nvsHandle, "ssid", &ssid));
			ESP_ERROR_CHECK(nvs_set_str(nvsHandle, "password", &password));
			ESP_ERROR_CHECK(nvs_commit(nvsHandle));
			nvs_close(nvsHandle);

			if (evt->type == SC_TYPE_ESPTOUCH_V2) {
				ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)) );
				// ESP_LOGI(TAG, "RVD_DATA:");
				// for (int i=0; i<33; i++) {
				// 	printf("%02x ", rvd_data[i]);
				// }
				// printf("\n");
			}

			ESP_ERROR_CHECK(esp_wifi_disconnect());
			ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifiConfig));
			esp_wifi_connect();
		}
	}
	else if(base == SC_EVENT) {
		if(id == SC_EVENT_SEND_ACK_DONE) {
			xEventGroupSetBits(eventGroup, EVENT_WIFI_ESPTOUCH_DONE);
		}
	}
}

static void wifiSmartconfig(void *arg) {
	EventBits_t uxBits;
    ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS));
    smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_smartconfig_start(&cfg));
    while (1) {
        uxBits = xEventGroupWaitBits(
			eventGroup,
			EVENT_WIFI_CONNECTED | EVENT_WIFI_ESPTOUCH_DONE,
			true,
			false,
			portMAX_DELAY
		);
        if(uxBits & EVENT_WIFI_CONNECTED) {
			pageInfoAdd("WiFi Connected to ap");
            // ESP_LOGI(TAG, "WiFi Connected to ap");
        }
        if(uxBits & EVENT_WIFI_ESPTOUCH_DONE) {
			pageInfoAdd("WIFI smartconfig done.");
            // ESP_LOGI(TAG, "smartconfig over");
            esp_smartconfig_stop();
            vTaskDelete(NULL);
        }
    }
}



static void wifiCheckWifiCon() {
	esp_err_t err;
	pageInfoAdd("Check WIFI config in NVS...");
	err = nvs_open("wifiConfig", NVS_READWRITE, &nvsHandle);
	if(err != ESP_OK) {
		pageInfoAdd("Open NVS failed. Start WIFI config...");
		wifiConType = 1;
	}
	else {
		uint8_t wifiConfigFlag;
		err = nvs_get_u8(nvsHandle, "wifiConfigFlag", &wifiConfigFlag);
		if(err != ESP_OK) {
			pageInfoAdd("No WIFI config data in NVS. Start smartconfig...");
			nvs_close(nvsHandle);
			wifiConType = 1;
		}
		else {
			if(wifiConfigFlag == 0) {
				pageInfoAdd("No WIFI config data in NVS. Start smartconfig...");
				nvs_close(nvsHandle);
				wifiConType = 1;
			}
			else {
				bool check = true;
				uint8_t ssid[33] = {0};
				uint8_t password[65] = {0};
				size_t getSize = 0;
				size_t passwordSize = sizeof(password);
				getSize = sizeof(ssid);
				err = nvs_get_str(nvsHandle, "ssid", &ssid, &getSize);

				if(err != ESP_OK) {
					check = false;
				}
				err = nvs_get_str(nvsHandle, "password", &password, &passwordSize);
				if(err != ESP_OK) {
					check = false;
				}

				nvs_close(nvsHandle);

				if(check == false) {
					pageInfoAdd("Get WIFI config data from NVS failed. Start WIFI config...");
					wifiConType = 1;
				}
				else {
					pageInfoAdd("Got WIFI config data from NVS. Try to connect...");
					
					bzero(&wifiConfig, sizeof(wifi_config_t));
					memcpy(wifiConfig.sta.ssid, ssid, sizeof(wifiConfig.sta.ssid));
					memcpy(wifiConfig.sta.password, password, sizeof(wifiConfig.sta.password));

					ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifiConfig));
				}
			}
		}
	}
}



#endif